package com.nononsenseapps.feeder.ui.common;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.nononsenseapps.feeder.util.ScreenUtils;

import timber.log.Timber;

public class DragFloatActionButton extends FloatingActionButton {

    private int screenWidth;
    private int screenHeight;
    private int screenWidthHalf;
    private int statusHeight;
    private int virtualHeight;
    private boolean autoKeepSide=false;
    private boolean isLongClickModule;

    private Handler handler;
    private int clickCount = 0;//记录连续点击次数
    private Runnable doubleClickCheckRun=null;
    private Runnable longClickCheckRun=null;
    /**
     * 自定义回调接口
     */
    private DoubleClickCallback mCallback;

    private LongClickCallback mLongClickCallback;

    public interface DoubleClickCallback {
        void onDoubleClick();
    }

    public interface LongClickCallback {
        void onLongClick();
    }

    public DragFloatActionButton(Context context) {
        super(context);
        init();
    }

    public DragFloatActionButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        screenWidth = ScreenUtils.getScreenWidth(getContext());
        screenWidthHalf = screenWidth / 2;
        screenHeight = ScreenUtils.getScreenHeight(getContext());
        statusHeight = ScreenUtils.getStatusHeight(getContext());
        virtualHeight=ScreenUtils.getVirtualBarHeigh(getContext());
        handler = new Handler();
    }

    private int lastX;
    private int lastY;

    private boolean isDrag;

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                isLongClickModule=isDrag = false;
                getParent().requestDisallowInterceptTouchEvent(true);
                lastX = rawX;
                lastY = rawY;
                //Log.e("down---->", "getX=" + getX() + "；screenWidthHalf=" + screenWidthHalf);
                clickCount++;
                if(clickCount==1) {
                    longClickCheckRun=()->{
                        isLongClickModule =true;
                        Timber.d( "longClick checked");
                    };
                    handler.postDelayed(longClickCheckRun, 300);//长按时间
                    doubleClickCheckRun = () -> {
                        if(!isDrag) {
                            if (clickCount == 1) {
                                if (isLongClickModule) {
                                    Timber.d( "longClick called");
                                    if (mLongClickCallback != null)
                                        mLongClickCallback.onLongClick();
                                    isLongClickModule = false;
                                } else
                                    performClick();
                            } else if (clickCount == 2) {
                                Timber.d( "doubleClick called");
                                if (mCallback != null)
                                    mCallback.onDoubleClick();
                            }
                        }
                        handler.removeCallbacksAndMessages(this);
                        //清空handler延时，并防内存泄漏
                        clickCount = 0;//计数清零
                        doubleClickCheckRun=null;
                    };
                    handler.postDelayed(doubleClickCheckRun, 400);//双击间隔
                }
                break;
            case MotionEvent.ACTION_MOVE:
                //当滑动时背景为选中状态 //检测是否长按,在非长按时检测
                /*if (!isLongClickModule) {
                    isLongClickModule = isLongPressed(event.getDownTime(), event.getEventTime(), 300);
                    Timber.d( "longClick checked");
                }*/
                if(isLongClickModule){
                    //计算手指移动了多少
                    int dx = rawX - lastX;
                    int dy = rawY - lastY;

                    if(!isDrag) {
                        //这里修复一些手机无法触发点击事件的问题
                        int distance = (int) Math.sqrt(dx * dx + dy * dy);

                        //Log.e("distance---->", distance + "");
                        if (distance > 30) {//给个容错范围，不然有部分手机还是无法点击
                            isDrag = true;
                            Timber.d( "drag mode start with distance:%d",distance);
                        }
                    }
                    if(isDrag){
                        float x = getX() + dx;
                        float y = getY() + dy;

                        //检测是否到达边缘 左上右下
                        x = x < 0 ? 0 : x > screenWidth - getWidth() ? screenWidth - getWidth() : x;
                        // y = y < statusHeight ? statusHeight : (y + getHeight() >= screenHeight ? screenHeight - getHeight() : y);
                        if (y < 0) {
                            y = 0;
                        }
                        if (y > screenHeight - statusHeight - getHeight()) {
                            y = screenHeight - statusHeight - getHeight();
                        }
                        setX(x);
                        setY(y);

                        lastX = rawX;
                        lastY = rawY;
                        //Log.e("move---->", "getX=" + getX() + "；screenWidthHalf=" + screenWidthHalf + " " + isDrag+"  statusHeight="+statusHeight+ " virtualHeight"+virtualHeight+ " screenHeight"+ screenHeight+"  getHeight="+getHeight()+" y"+y);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (isDrag) {
                    //Log.e("ACTION_UP---->", "getX=" + getX() + "；screenWidthHalf=" + screenWidthHalf);
                    if(autoKeepSide) {
                        if (rawX >= screenWidthHalf) {
                            animate().setInterpolator(new DecelerateInterpolator())
                                    .setDuration(500)
                                    .xBy(screenWidth - getWidth() - getX())
                                    .start();
                        } else {
                            ObjectAnimator oa = ObjectAnimator.ofFloat(this, "x", getX(), 0);
                            oa.setInterpolator(new DecelerateInterpolator());
                            oa.setDuration(500);
                            oa.start();
                        }
                    }
                    isDrag = false;
                }
                setPressed(false);
                if(longClickCheckRun!=null) {
                    handler.removeCallbacks(longClickCheckRun);
                    longClickCheckRun = null;
                }
                break;
        }
        //如果是拖拽则消耗事件，否则正常传递即可。
        return true;//isDrag||doubleClickCheckRun!=null|| super.onTouchEvent(event);
    }

    public boolean isAutoKeepSide() {
        return autoKeepSide;
    }

    public void setAutoKeepSide(boolean autoKeepSide) {
        this.autoKeepSide = autoKeepSide;
    }

    public void setDoubleClickCallback(DoubleClickCallback mCallback) {
        this.mCallback = mCallback;
    }

    public void setLongClickCallback(LongClickCallback mLongClickCallback) {
        this.mLongClickCallback = mLongClickCallback;
    }

    /* 判断是否有长按动作发生
     * @param lastDownTime 按下时间
     * @param thisEventTime 移动时间
     * @param longPressTime 判断长按时间的阀值
     */
    private boolean isLongPressed(long lastDownTime, long thisEventTime,
                                  long longPressTime) {
        //float offsetX = Math.abs(thisX - lastX);
        //float offsetY = Math.abs(thisY - lastY);
        long intervalTime = thisEventTime - lastDownTime;
        if (intervalTime >= longPressTime) {
            return true;
        }
        return false;
    }
}